#include "service.h"

// output of the error messages for the user. error - internal number of error
// and input[] - is a relative text (when needed)
// error numers are in service.h in enum ERROR_NUM

void print_error(int error, unsigned char input[])
{
    switch (error)
    {
    case ARGS:
        printf("Incorrect argumets.\n");
        break;
    case FILENAME_INV_OR_NULL:
        printf("Inappropriate or null filename.\n");
        break;
    case OPENING_FILE:
        printf("Error opening file %s (probably doesn't exist or not enough system priviliges?).\n", input);
        break;
    case IGNORED_PARAMS:
        printf("Any paramerers after -%c are ignored.\n", input[1]);
        break;
    case NO_FILES:
        printf("No files to archive.\n");
        break;
    case NO_FREE_MEMORY:
        printf("Out of free memory.\n");
        break;
    case INVALID_ARC_OR_DAMAGED:
        printf("The file %s is not a valid archive or is damaged.\n", input);
        break;
    case CORRUPTED_FILE_IN_ARC:
        printf("The %s file in current archive is corrupted.\n", input);
        break;
    case UNKNOWN_PARAM:
        printf("Unknown parameter %c.\n", input[1]);
        break;
    case NOTUNIQUE_NAME:
        printf("There can't be several files with the same name in archive file. %s is already present.\n", input);
        break;
    case SUBTEST_FAIL:
        printf("Conflict found in archive %s. It's probably damaged.\n", input);
        break;
    case FILE_NOT_FOUND:
        printf("File %s wasn't found in archive.\n", input);
        break;
    case OPENING_TEMP_FILE:
        printf("Error while opening temp file (no free space on HDD?).\n");
        break;
    case MOVING_FILE:
        printf("Error while moving new created archive file %s.\n", input);
        break;
    case REMOVING_FILE:
        printf("Error while removing old archive file %s.\n", input);
        break;
    }
}

// traverse binary tree with names of files in arc.

void traverseArfileTree(arfile *root)
{
    if (!root)
        return;

    if (root->left)
        traverseArfileTree(root->left);

    printf("%s\t\t\t%zu\t\t%zu\n", root->name, root->offset, root->hash);

    if (root->right)
        traverseArfileTree(root->right);
}

void print_help_info()
{
    printf("%s", "Simple archiver using Huffman compression method. Usage:\n"\
	"arc -[axdlt] arc[.ext] file1 file2 …\n"\
	"\t-a (append)  – put files into new archive or append to existing one\n"\
	// "\t-X (eXtract) – extract files out of archive\n"
	"\t-x (extract) – extract files without changing paths\n"\
	    "to extract all files don't specify any options after archive file name\n"\
	"\t-d (delete)  – delete files from archive\n"\
	"\t-l (list)    – show information about files in archive\n"\
	"\t-t (test)    – check integrity of existing archive file\n");
}

// prints the list :-)

void print_list(list *head)
{
    list *p;
    int i = 0;
    printf("Number\tCode\tWeight\n");
    for (p = (head); p; p = p->next, i++)
        printf("%d\t%d\t%lld\n", i, p->tree->data, p->tree->weight);
}

//prints stats for how often every symbols is met in the file

void print_sym_freq_stat(unsigned char file_name[], unsigned long array[])
{
    int j;
    printf("File [%s] statistic:\n", file_name);
    for (j = 0; j < 256; j++)
        if (array[j])
            printf("Code [%3d]:\t[%ld]\n", j, array[j]);
}

// the simplest function for printing  out a tree

void tree_print(node *root)
{
    printf("Code: [%d]\tWeight: [%lld]\n", root->data, root->weight);
    if (root->left)
    {
        tree_print(root->left);
    }

    if (root->right)
    {
        tree_print(root->right);
    }
}

// a little bit better function for printing out a tree

void psgraph_tree_print(node *root, int offset)
{
    int i;
    char var2[] = "   ";
    char var[] = "/|\\";
    if (!root->left && !root->right)
    {
        for (i = 0; i < offset; i++)
        {
            printf("%s", var2);
        }
        printf("[%3d]\n", root->data);
    }
    else
    {
        for (i = 0; i < offset; i++)
        {
            printf("%s", var2);
        }
        printf("[%s]\n", var);
    }

    if (root->left)
    {
        psgraph_tree_print(root->left, offset + 1);
    }

    if (root->right)
    {
        psgraph_tree_print(root->right, offset + 1);
    }
}


// prints out a byte in binary code

inline void print_binary(unsigned char var)
{
    int i;
    for (i = 1; i <= CHAR_BIT; i++)
        printf("%d", (1 & (var >> (CHAR_BIT - i))));
}


